﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Wimm.Common.Entities.Utils;
using Wimm.Common.Interfaces.Utils;
using Windows.UI.Core;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;

namespace Wimm.CustomContols
{
    abstract public class GenericDataGridControl<DalClass, CurClass>: Control, INotifyPropertyChanged
    {
        protected int  currentPage = 0;
        protected bool newItemsExists = true;
        protected bool loadedHanded = false;
        protected object Sender;

        #region Dependency Properties

        #region PagedGridData

        public PagedGridData<DalClass, CurClass> PagedGridData
        {
            get 
            { 
                return GetValue(PagedGridDataProperty) as PagedGridData<DalClass, CurClass>; 
            }
            set 
            {
                SetValue(PagedGridDataProperty, value); 
            }
        }

        public static readonly DependencyProperty PagedGridDataProperty =
            DependencyProperty.Register("PagedGridData", typeof(PagedGridData<DalClass, CurClass>),
            typeof(GenericDataGridControl<DalClass, CurClass>), new PropertyMetadata(null));

        #endregion

        #region ItemTemplate

        public DataTemplate ItemTemplate
        {
            get { return (DataTemplate)GetValue(ItemTemplateProperty); }
            set
            {
                SetValue(ItemTemplateProperty, value); 
            }
        }

        public static readonly DependencyProperty ItemTemplateProperty =
            DependencyProperty.Register("ItemTemplate", typeof(DataTemplate),
            typeof(GenericDataGridControl<DalClass, CurClass>), new PropertyMetadata(null));
        #endregion

        #region HeaderTemplate

        public DataTemplate HeaderTemplate
        {
            get { return (DataTemplate)GetValue(HeaderTemplateProperty); }
            set 
            { 
                SetValue(HeaderTemplateProperty, value); 
            }
        }

        public static readonly DependencyProperty HeaderTemplateProperty =
            DependencyProperty.Register("HeaderTemplate", typeof(DataTemplate),
            typeof(GenericDataGridControl<DalClass, CurClass>), new PropertyMetadata(null));

        #endregion

        #region ProgressVisibility
        public Visibility ProgressVisibility
        {
            get { return (Visibility)GetValue(ProgressVisibilityProperty); }
            set { SetValue(ProgressVisibilityProperty, value); }
        }

        // Using a DependencyProperty as the backing store for ProgressVisibility.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ProgressVisibilityProperty =
            DependencyProperty.Register("ProgressVisibility", typeof(Visibility), typeof(GenericDataGridControl<DalClass, CurClass>), new PropertyMetadata(0));        
        
        #endregion

        #endregion
        
        /// <summary>
        /// Async event for scroll changing
        /// if scroll in the end, load more items
        /// </summary>
        /// <param name="sender"> Type <see cref="ScrollViewer"/></param>
        /// <param name="e"></param>
        protected async void ScrollViewer_ViewChanged(object sender, ScrollViewerViewChangedEventArgs e)
        {
            var scrollviewer = sender as ScrollViewer;
            if (scrollviewer.VerticalOffset == scrollviewer.ScrollableHeight && !e.IsIntermediate && newItemsExists)
            {
                Debug.WriteLine("ScrollViewer_ViewChanged: load next items");
                await GetNextPageItems();
            }
        }

        protected async void ScrollViewer_Loaded(object sender, RoutedEventArgs e) 
        {
            this.ProgressVisibility = Visibility.Visible;
            var scrollviewer = sender as ScrollViewer;
            bool isItemExists;
            do
            {
                isItemExists = await GetNextPageItems();
            }
            while (scrollviewer.ExtentHeight == 0 && isItemExists && PagedGridData.IsPagingEnabled);
            this.ProgressVisibility = Visibility.Collapsed;
        }

        private async Task<bool> GetNextPageItems()
        {
            if (this.PagedGridData == null)
                return false;

            await Task.Delay(100);

            var items = (await GetNewItems()).Data;
            if (items.Count > 0)
            {
                newItemsExists = PagedGridData.IsPagingEnabled ? !(items.Count() < PagedGridData.ItemsOnPage) : false;
                foreach (var item in items)
                {
                    PagedGridData.ItemsList.Add(item);
                }
                currentPage++;
                return newItemsExists;
            }
            return false;
        }

        /// <summary>
        /// Async get new items
        /// </summary>
        /// <returns></returns>
        private async Task<IPagedResult<CurClass>> GetNewItems()
        {
            IPagedRequest<DalClass> request = PagedGridData.IsPagingEnabled
                                        ? GetNextPage(this.currentPage, this.PagedGridData.ItemsOnPage)
                                        : GetNextPage(this.currentPage, Int32.MaxValue);

            return await ((PagingFunctionSource<DalClass, CurClass>)this.PagedGridData.Source).Function(request);
        }

        protected abstract IPagedRequest<DalClass> GetNextPage(int currentPage, int itemsOnPage);

        #region INotifyPropertyChanged
        public void OnPropertyChanged(string args)
        {
            if (this.PropertyChanged != null)
                this.PropertyChanged(this, new PropertyChangedEventArgs(args));
        }

        public event PropertyChangedEventHandler PropertyChanged;


        #endregion    

    }
}
